﻿using System;
using System.Collections;
using System.Linq;
using System.Runtime.Caching;

namespace Raise.Monitor.Services {
    public class CacheBuffer {
        private static CacheBuffer Default => new CacheBuffer();
        private readonly MemoryCache _cache = MemoryCache.Default;
        private readonly object _locker = new object();

        private bool SetToCache(string key, object value, CacheItemPolicy policy) {
            lock(_locker) {
                _cache.Set(key, value, policy);
                return true;
            }
        }

        private object GetFromCache(string key) {
            lock(_locker) {
                if(_cache.Contains(key)) {
                    return _cache[key];
                }
                return null;
            }
        }

        private ICollection GetCacheKeys() {
            lock(_locker) {
                var items = _cache.AsEnumerable();
                return items.Select(m => m.Key).ToList();
            }
        }

        private bool ContainKey(string key) {
            lock(_locker) {
                return _cache.Contains(key);
            }
        }

        private bool RemoveFromCache(string key) {
            lock(_locker) {
                if(_cache.Contains(key)) {
                    _cache.Remove(key);
                    return true;
                }
                return false;
            }
        }

        private void ClearCache() {
            lock(_locker) {
                _cache.ToList().ForEach(m => _cache.Remove(m.Key));
            }
        }

        private ICollection GetValues<T>() {
            lock(_locker) {
                var items = _cache.AsEnumerable();
                return items.Select(m => (T)m.Value).ToList();
            }
        }

        private long GetCacheSize() {
            lock(_locker) {
                return _cache.GetCount();
            }
        }

        public static object Get(string key) {
            return Default.GetFromCache(key);
        }

        public static bool Set(string key, Object value, TimeSpan expiresIn) {
            var policy = new CacheItemPolicy() {
                SlidingExpiration = expiresIn
            };
            return Default.SetToCache(key, value, policy);
        }

        public static bool Set(string key, Object value, DateTimeOffset expiresIn) {
            var policy = new CacheItemPolicy() {
                AbsoluteExpiration = expiresIn
            };
            return Default.SetToCache(key, value, policy);
        }

        public static bool Set(string key, object value) {
            CacheItemPolicy policy = new CacheItemPolicy() {
                Priority = CacheItemPriority.NotRemovable,
            };
            return Default.SetToCache(key, value, policy);
        }

        public static bool Remove(string key) {
            return Default.RemoveFromCache(key);
        }

        public static void Clear() {
            Default.ClearCache();
        }

        public static ICollection Values<T>() {
            return Default.GetValues<T>();
        }

        public static bool Contain(string key) {
            return Default.ContainKey(key);
        }

        public static long Size() {
            return Default.GetCacheSize();
        }

        public static ICollection Keys() {
            return Default.GetCacheKeys();
        }

        public CacheBuffer() {
            //CacheItemPolicy policy = new CacheItemPolicy();  //创建缓存项策略
            ////过期时间设置,以下两种只能设置一种
            //policy.AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddMinutes(5)); //设定某个时间过后将逐出缓存
            //policy.SlidingExpiration = new TimeSpan(0, 0, 10);    //设定某个时间段内未被访问将逐出缓存
            ////逐出通知,以下两种只能设置一种
            //policy.UpdateCallback = arguments => { Console.WriteLine("即将逐出缓存" + arguments.Key); };
        }
    }
}
